#ifndef _MULTIPARTREADER_HPP_
#define _MULTIPARTREADER_HPP_

#include "jhdefs.hpp"
#include "stream/streambuf.hpp"
using JHCPP::stream::BufferedStreamBuf;
#include <istream>
#include <string>

NET_NAMESPACE_BEGIN

class CMessageHeader;
class CMultipartStreamBuf : public BufferedStreamBuf
{
public:
	CMultipartStreamBuf(std::istream& istr, const std::string& boundary);
	~CMultipartStreamBuf();
	bool lastPart() const;

protected:
	int readFromDevice(char* buffer, std::streamsize length);

private:
	enum 
	{
		STREAM_BUFFER_SIZE = 1024
	};

	std::istream& m_istr;
	std::string   m_boundary;
	bool          m_lastPart;
};

class CMultipartIOS : public virtual std::ios
{
public:
	CMultipartIOS(std::istream& istr, const std::string& boundary);
	~CMultipartIOS();
	CMultipartStreamBuf* rdbuf();
	bool lastPart() const;

protected:
	CMultipartStreamBuf m_buf;
};


class CMultipartInputStream : public CMultipartIOS, public std::istream
{
public:
	CMultipartInputStream(std::istream& istr, const std::string& boundary);
	~CMultipartInputStream();
};


class CMultipartReader
{
public:
	explicit CMultipartReader(std::istream& istr);
	CMultipartReader(std::istream& istr, const std::string& boundary);
	~CMultipartReader();

	void nextPart(CMessageHeader& messageHeader);
	bool hasNextPart();
	std::istream& stream() const;
	const std::string& boundary() const;

protected:
	void findFirstBoundary();
	void guessBoundary();
	void parseHeader(CMessageHeader& messageHeader);
	bool readLine(std::string& line, std::string::size_type n);

private:
	CMultipartReader();
	CMultipartReader(const CMultipartReader&);
	CMultipartReader& operator = (const CMultipartReader&);

	std::istream&         m_istr;
	std::string           m_boundary;
	CMultipartInputStream* m_pMPI;
};
NET_NAMESPACE_END

#endif
